<?php
namespace catchAdmin\wechatopen\controller;

use app\BaseController;
use catchAdmin\login\request\LoginRequest;
use catchAdmin\permissions\model\Users;
use catchAdmin\wechatopen\request\CreateRequest;
use catchAdmin\wechatopen\model\Applet;
use catcher\base\CatchController;
use catcher\base\CatchRequest as Request;
use catcher\CatchAuth;
use catcher\CatchResponse;
use catcher\Code;
use catcher\exceptions\LoginFailedException;
use catcher\Utils;
use EasyWeChat\OpenPlatform\Application;
use thans\jwt\facade\JWTAuth;
use uctoo\ThinkEasyWeChat\OpenPlatform\Website\ServiceProvider;
use think\facade\Log;
use catchAdmin\wechatopen\model\WechatopenUsers;

class WechatLogin extends BaseController
{
    /**
     * applet 实例
     * @var \catchAdmin\wechatopen\model\Applet
     */
    protected $applet;

    public function initialize()
    {

    }


    /**
     * 微信扫码后如没有后台帐号，则注册后台帐号
     * @time 2021年05月31日 18:52
     * @param Request $request
     */
    public function wechatregist(CreateRequest $request,Application $app)
    {
        //TODO:通过https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID 验证扫码登录权限，失败则不允许注册帐号
        $access_token = input('access_token');
        $openid = input('openid');
        $wechatUser = WechatopenUsers::where('openid','=',input('openid'))->find();
        if(!$wechatUser){
            return CatchResponse::fail('无关联的微信帐号', Code::LOGIN_FAILED);
        }
        Log::write($access_token,'debug');
        Log::write($openid,'debug');
        $website = $app->register(new ServiceProvider)->website;
        Log::write("wechatregist",'debug');
        $res = $website->auth($access_token,$openid);    //通过微信扫码登录code获取access_token
        Log::write($res,'debug');
        if(0 != $res['errcode']){  //微信扫码登录access_token 无效
            return CatchResponse::fail('微信扫码登录授权无效', Code::LOGIN_FAILED);
        }

        $user = new Users;
        $param = $request->param();
        $param['avatar'] = $wechatUser['headimgurl'];  //后台管理员使用扫码的微信作为初始头像
        $res = $user->storeBy($param);
        Log::write($res,'debug');
        Log::write("user",'debug');
        Log::write($user,'debug');
        $user->attachRoles([2]);  //TODO:获取后台配置的默认用户组

        if ($request->param('jobs')) {
            $user->attachJobs($request->param('jobs'));
        }
        //微信用户添加关联的后台帐号
       if($wechatUser['user_ids']){ //
          $arrayIds = json_decode($wechatUser['user_ids'],true);
          array_push($arrayIds,$res);
          $wechatUser->user_ids = json_encode($arrayIds);
       }else{
          $wechatUser->user_ids =  json_encode([$res]);
       }

        $wechatUser->save();
        //TODO：注册后直接登录

        return CatchResponse::success($user, '添加成功');
    }


    /**
     * 微信扫码后获取后台帐号,在微信扫码后跳转到的页面先调用此接口
     * @time 2021年05月31日 18:52
     * @param Request $request
     * @param string code
     * @param string state
     */
    public function wechatoauth(Application $app)
    {
        $code = input('code');
        if(!isset($code)){
            return CatchResponse::fail('缺少code参数', Code::LOGIN_FAILED);
        }

        $query['appid'] = Utils::config('website.appid');
        $query['secret'] = Utils::config('website.appsecret');
        $query['code'] = $code;
        $query['grant_type'] = 'authorization_code';
        Log::write($code,'debug');
        Log::write($query,'debug');
        $website = $app->register(new ServiceProvider)->website;
        Log::write("website",'debug');
        $res = $website->snsAccessToken($query);    //通过微信扫码登录code获取access_token
        Log::write("res",'debug');
        Log::write($res,'debug');
       /* array (
            'access_token' => '45_mpewTQxTSJfk14mQzoqi8SiEwLk8kgcc-pZdDRMRB3lYk6_VTlgBQb9WAu32CUwiwlZCO4eSWWvaMfwVzx-ruLZHAFXS-9GQ5jOmXmbFgvE',
            'expires_in' => 7200,
            'refresh_token' => '45_r2NZ-ZZp7ozc6294YpIqq-2iNb-2ntz0dIo777Zx7DcfbQ-rka6Pmw4Db_1HCERuv3T7Yga6t8dQcDSdPOi7rCSKuOJS2ygtlu5brZXz5Fg',
            'openid' => 'odlJFswJLBoc3dIMczz7-_yOqxZg',
            'scope' => 'snsapi_login',
            'unionid' => 'o0Pr6s6dH4HLZtTkee9WY37_xJJE',
        )*/
       if(!isset($res['openid'])){
           return CatchResponse::fail('微信扫码登录授权失败', Code::LOGIN_FAILED);
       }
       //查询微信开放平台用户表
        $wechatUser = WechatopenUsers::where('openid','=',$res['openid'])->find();
       if($wechatUser){ //已有微信用户返回关联的后台帐号
           $accountList = Users::where('id','in',json_decode($wechatUser['user_ids'],true))->field('id,username,email')->select();
           $accountList['openid'] = $res['openid'];
           $accountList['access_token'] = $res['access_token'];
           Log::write("accountList",'debug');
           Log::write($accountList,'debug');
           return CatchResponse::success(['accountList' => $accountList], '获取帐号列表成功');

       }else{ //新用户记录帐号信息，返回空的关联后台帐号，前端引导用户注册帐号
           $result = $website->userinfo($res['access_token'],$res['openid']);
           Log::write("result",'debug');
           Log::write($result,'debug');
           if(isset($result['openid'])){  //随缘获取用户信息，没有就用授权信息记录匿名帐号
               $newwechatUser = new WechatopenUsers;
               $newwechatUser->appid = Utils::config('website.appid');
               $newwechatUser->openid = $result['openid'];
               $newwechatUser->unionid = $result['unionid'];
               $newwechatUser->access_token = $res['access_token'];
               $newwechatUser->access_token_overtime = time()+$res['expires_in'];
               $newwechatUser->refresh_token = $res['refresh_token'];
               $newwechatUser->status = 1;
               $newwechatUser->loginip = request()->ip();
               $newwechatUser->nickname = $result['nickname'];
               $newwechatUser->sex = $result['sex'];
               $newwechatUser->province = $result['province'];
               $newwechatUser->city = $result['city'];
               $newwechatUser->country = $result['country'];
               $newwechatUser->headimgurl = $result['headimgurl'];
               $newwechatUser->privilege = json_encode($result['privilege']);
               //$newwechatUser->user_ids = '';
               $newwechatUser->save();
               $accountList['openid'] = $res['openid'];
               $accountList['access_token'] = $res['access_token'];
               return CatchResponse::success(['accountList' => $accountList], '获取帐号列表成功');
           }else{
               $newwechatUser = new WechatopenUsers;
               $newwechatUser->appid = Utils::config('website.appid');
               $newwechatUser->openid = $res['openid'];
               $newwechatUser->unionid = $res['unionid'];
               $newwechatUser->access_token = $res['access_token'];
               $newwechatUser->access_token_overtime = time()+$res['expires_in'];
               $newwechatUser->refresh_token = $res['refresh_token'];
               $newwechatUser->status = 1;
               $newwechatUser->loginip = request()->ip();
               //$newwechatUser->user_ids = json_encode([]);
               $newwechatUser->save();
               $accountList['openid'] = $res['openid'];
               $accountList['access_token'] = $res['access_token'];
               return CatchResponse::success(['accountList' => $accountList], '获取帐号列表成功');
           }
       }
    }


    /**
     * 微信扫码后登录后台帐号
     * @time 2021年05月31日 18:52
     * @param Request $request
     */
    public function wechatlogin(LoginRequest $request, CatchAuth $auth,Application $app)
    {
        $condition = $request->param();

        try {
            //TODO:通过https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID 验证扫码登录权限，失败则不允许登录帐号
            $access_token = input('access_token');
            $openid = input('openid');
            Log::write($access_token,'debug');
            Log::write($openid,'debug');
            $website = $app->register(new ServiceProvider)->website;
            Log::write("wechatlogin",'debug');
            $res = $website->auth($access_token,$openid);    //通过微信扫码登录code获取access_token
            Log::write($res,'debug');
            if(0 != $res['errcode']){  //微信扫码登录access_token 无效
                return CatchResponse::fail('微信扫码登录授权无效', Code::LOGIN_FAILED);
            }

            $auth->ignorePasswordVerify(); //跳过密码验证
            $token = $auth->attempt($condition);

            $user = $auth->user();

            $this->afterLoginSuccess($user, $token);
            // 登录事件
            $this->loginEvent($user->username);

            return CatchResponse::success([
                'token' => $token,
            ], '登录成功');
        } catch (\Exception $exception) {
            $this->detailWithLoginFailed($exception, $condition);
            $code = $exception->getCode();
            return CatchResponse::fail($code == Code::USER_FORBIDDEN ?
                '该账户已被禁用，请联系管理员' : '登录失败,请检查邮箱和密码', Code::LOGIN_FAILED);
        }
    }

    /**
     * 处理登录失败
     *
     * @time 2020年10月26日
     * @param $exception
     * @param $condition
     * @return void
     */
    protected function detailWithLoginFailed($exception, $condition)
    {
        $message = $exception->getMessage();

        if (strpos($message, '|') !== false) {
            $username = explode('|', $message)[1];
        } else {
            $username = $condition['email'];
        }

        $this->loginEvent($username, false);
    }

    /**
     * 用户登录成功后
     *
     * @time 2020年09月09日
     * @param $user
     * @param $token
     * @return void
     */
    protected function afterLoginSuccess($user, $token)
    {
        $user->last_login_ip = request()->ip();
        $user->last_login_time = time();
        if ($user->hasField('remember_token')) {
            $user->remember_token = $token;
        }
        $user->save();
    }

    /**
     * 登录事件
     *
     * @time 2020年09月09日
     * @param $name
     * @param bool $success
     * @return void
     */
    protected function loginEvent($name, $success = true)
    {
        $params['login_name'] = $name;
        $params['success'] = $success ? 1 : 2;
        event('loginLog', $params);
    }


    /**
     * 登出
     *
     * @time 2019年11月28日
     * @return \think\response\Json
     */
    public function logout(): \think\response\Json
    {
        return CatchResponse::success();
    }

    /**
     * refresh token
     *
     * @author JaguarJack
     * @email njphper@gmail.com
     * @time 2020/5/18
     * @return \think\response\Json
     */
    public function refreshToken()
    {
        return CatchResponse::success([
            'token' => JWTAuth::refresh()
        ]);
    }
}
